package com.jprocms.module.cms.service.globalconfig;

import cn.hutool.core.lang.Assert;
import com.baomidou.dynamic.datasource.annotation.Master;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jpro.framework.common.pojo.CommonResult;
import com.jpro.framework.common.util.object.BeanUtils;
import com.jpro.module.infra.api.config.ConfigApi;
import com.jpro.module.infra.api.config.FileConfigApi;
import com.jpro.module.infra.api.config.dto.ConfigUpdateReqVO;
import com.jpro.module.infra.api.config.dto.FileConfigRespVO;
import com.jpro.module.infra.framework.file.core.client.ftp.FtpFileClientConfig;
import com.jpro.module.infra.framework.file.core.client.local.LocalFileClientConfig;
import com.jprocms.module.cms.api.dto.EmailConfig;
import com.jprocms.module.cms.api.dto.RegisterConfig;
import com.jprocms.module.cms.api.dto.SecurityConfig;
import com.jprocms.module.cms.api.dto.UploadConfig;
import com.jprocms.module.cms.config.JproProperties;
import com.jprocms.module.cms.controller.admin.globalconfig.vo.GlobalConfigUpdateReqVO;
import com.jprocms.module.cms.convert.globalconfig.GlobalConfigConvert;
import com.jprocms.module.cms.dal.dataobject.globalconfig.GlobalConfigDO;
import com.jprocms.module.cms.dal.mysql.globalconfig.GlobalConfigMapper;
import com.jprocms.module.cms.framework.file.core.enums.FileStorageEnum;
import com.mzt.logapi.context.LogRecordContext;
import com.mzt.logapi.service.impl.DiffParseFunction;
import com.mzt.logapi.starter.annotation.LogRecord;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;

import static com.jpro.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.jprocms.module.cms.constant.CmsSysConstants.TPL_STORE_TYPE_CONFIG_ID;
import static com.jprocms.module.cms.enums.ErrorCodeConstants.GLOBAL_CONFIG_NOT_EXISTS;
import static com.jprocms.module.cms.enums.LogRecordConstants.*;

/**
 * 系统配置 Service 实现类
 *
 * @author jprocms
 */
@Master
@Service
@Validated
public class GlobalConfigServiceImpl extends ServiceImpl<GlobalConfigMapper, GlobalConfigDO> implements GlobalConfigService {

    @Resource
    private GlobalConfigMapper globalConfigMapper;

    @Resource
    private JproProperties jproProperties;
    @Resource
    private ConfigApi configApi;
    @Resource
    private FileConfigApi fileConfigApi;

    @Override
    @LogRecord(type = CMS_GLOBALCONFIG_TYPE, subType = CMS_GLOBALCONFIG_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", success = CMS_GLOBALCONFIG_UPDATE_SUCCESS)
    public void updateGlobalConfig(GlobalConfigUpdateReqVO updateReqVO) {
        // 校验存在
        final GlobalConfigDO globalConfigDO = validateGlobalConfigExists(updateReqVO.getId());
        LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(globalConfigDO, GlobalConfigUpdateReqVO.class));

        String newResDomain = validateGlobalConfigChangeTplStore(updateReqVO);
        // 更新
        GlobalConfigDO updateObj = GlobalConfigConvert.INSTANCE.convert(updateReqVO);
        if (StringUtils.isNotBlank(newResDomain)) {
            updateObj.setTplStoreConfigDomain(newResDomain);
        }
        if(updateObj.getPort()==null){
            LambdaUpdateWrapper<GlobalConfigDO> wrapper = new LambdaUpdateWrapper<>();
            wrapper.set(GlobalConfigDO::getPort, null);
            globalConfigMapper.update(new GlobalConfigDO(), wrapper);
        }
        globalConfigMapper.updateById(updateObj);
    }


    private GlobalConfigDO validateGlobalConfigExists(Integer id) {
        final GlobalConfigDO globalConfigDO = globalConfigMapper.selectById(id);
        if (globalConfigDO == null) {
            throw exception(GLOBAL_CONFIG_NOT_EXISTS);
        }
        return globalConfigDO;
    }

    private String validateGlobalConfigChangeTplStore(GlobalConfigUpdateReqVO updateReqVO) {
        GlobalConfigDO globalConfigDO = globalConfigMapper.selectById(updateReqVO.getId());
        String resDomain = "";
        if (!globalConfigDO.getTplStoreConfigId().equals(updateReqVO.getTplStoreConfigId())) {
            //模板配置变更刷新 TplServiceImpl 需要的获取infra服务中的配置信息
            ConfigUpdateReqVO configBaseVO = new ConfigUpdateReqVO();
            configBaseVO.setName(TPL_STORE_TYPE_CONFIG_ID).setValue(updateReqVO.getTplStoreConfigId().toString());
            configApi.updateConfigForApi(configBaseVO);

            Integer tplStorerageConfigId = updateReqVO.getTplStoreConfigId();
            CommonResult<FileConfigRespVO> fileConfigResult = fileConfigApi.getFileConfig(tplStorerageConfigId.longValue());
            if (fileConfigResult.isSuccess()) {
                FileConfigRespVO config = fileConfigResult.getData();
                if (FileStorageEnum.LOCAL.getStorage().equals(config.getStorage())) {
                    LocalFileClientConfig localFileClientConfig = (LocalFileClientConfig) config.getConfig();
                    resDomain = localFileClientConfig.getDomain();
                } else if (FileStorageEnum.FTP.getStorage().equals(config.getStorage())
                        || FileStorageEnum.SFTP.getStorage().equals(config.getStorage())) {
                    FtpFileClientConfig ftpFileClientConfig = (FtpFileClientConfig) config.getConfig();
                    resDomain = ftpFileClientConfig.getDomain();
                }
            }
        }
        return resDomain;
    }

    @Override
    public GlobalConfigDO getGlobalConfig(Integer id) {
        return globalConfigMapper.selectById(id);
    }

    @Override
    public GlobalConfigDO getDefGlobalConfig() {
        GlobalConfigDO globalConfig = getGlobalConfig(1);
        Assert.notNull(globalConfig, () -> {
            throw exception(GLOBAL_CONFIG_NOT_EXISTS);
        });
        globalConfig.setUploadsBlacklist(jproProperties.getUploadsBlacklist());
        initGlobalConfig(globalConfig);
        return globalConfig;
    }

    //初始化数据避免空前端不好处理
    private void initGlobalConfig(GlobalConfigDO globalConfig) {
        if (globalConfig.getUploadConfig() == null) {
            globalConfig.setUploadConfig(new UploadConfig());
        }
        if (globalConfig.getEmailConfig() == null) {
            globalConfig.setEmailConfig(new EmailConfig());
        }
        if (globalConfig.getSecurityConfig() == null) {
            globalConfig.setSecurityConfig(new SecurityConfig());
        }
        if (globalConfig.getRegisterConfig() == null) {
            globalConfig.setRegisterConfig(new RegisterConfig());
        }
    }
}
